package com.xiaobai.units;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description:
 * @author: 小白白
 * @create: 2021-11-21
 **/

@Slf4j
public class PytorchSocket {

    private static LinkedBlockingQueue<CodeTask> blockingQueue = new LinkedBlockingQueue<>();
    private static volatile boolean flag;
    private static Socket socket;

    public static void addTask(CodeTask codeTask) {
        if (!flag) {
            log.info("现在去连接");
            try {
                init();
            } catch (IOException e) {
                log.error("严重错误, python验证码识别程序未打开");
            }
        }
        blockingQueue.add(codeTask);
    }

    // 防止重复socket
    private static synchronized void init() throws IOException {
        if (flag) {
            return;
        }
        socket = new Socket("127.0.0.1", 9898);
        new Thread(() -> {
            flag = true;
            InputStream inputStream = null;
            OutputStream outputStream = null;
            byte[] bytes = new byte[6];
            while (true) {
                // 防止过错误识别,一次给了4个以上的字符
                for (int i = 4; i < bytes.length; i++) {
                    bytes[i] = 0;
                }
                CodeTask codeTask = null;
                try {
                    log.info("等待获取任务");
                    codeTask = blockingQueue.take();
                    log.info("获取到了任务");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 从阻塞队列中获取文件路径容器
                String filePath = codeTask.getFilePath();
                if (!socket.isConnected() || socket.isClosed()) {
                    try {
                        socket = new Socket("127.0.0.1", 9898);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    inputStream = socket.getInputStream();
                    outputStream = socket.getOutputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    // 发送文件地址
                    outputStream.write(filePath.getBytes());
                    // 阻塞读取识别结果
                    inputStream.read(bytes);
                } catch (IOException e) {
                    e.printStackTrace();
                    // 识别失败
                    codeTask.setResult(null);
                    continue;
                }
                String code = new String(bytes);
                // 塞入容器,继续循环
                codeTask.setResult(code);
            }
        }).start();
    }

    public static class CodeTask {

        private volatile Lock lock;
        private volatile Condition condition;

        private String filePath;

        private String result;

        public CodeTask(String filePath) {
            this.filePath = filePath;
            this.lock = new ReentrantLock();
            condition = lock.newCondition();
        }

        public void setResult(String result) {
            this.result = result;
            lock.lock();
            condition.signal();
            lock.unlock();
        }

        public String getResult() throws InterruptedException {
            lock.lock();
            condition.await(15, TimeUnit.SECONDS);
            lock.unlock();
            return this.result;
        }

        public String getFilePath() {
            return filePath;
        }

    }

    public static void main(String[] args) {
    }

}
